package com.zte.cloudservice.yige.view.widget;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;

/**
 * Created by wei on 2017/4/10.
 */

public class ScrollLinearLayout extends LinearLayout {

    private static final int SCROLL_BACK_DURATION = 500;
    private static final float DEFAULT_MOVE_RATIO = 4;
    private static final int RATION_CONTROL = 40;
    private float moveRatio;
    private float cDownY;
    private int mActivePointerId;

    public ScrollLinearLayout(Context context) {
        this(context, null);
    }

    public ScrollLinearLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    private void initView(Context context) {
        moveRatio = DEFAULT_MOVE_RATIO;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                cDownY = ev.getY(0);
                mActivePointerId = ev.getPointerId(0);
            case MotionEvent.ACTION_MOVE:
                final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                if (activePointerIndex == -1) {
                    break;
                }
                float mXMove = ev.getY(activePointerIndex);
                float diff = mXMove - cDownY;
                float absDiff = Math.abs(diff);
                if (canScrollVertically(diff) && absDiff > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
                    return true;
                }
            default:
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_MOVE:
                int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                if (activePointerIndex == -1) {
                    break;
                }
                int move = (int) (ev.getY(activePointerIndex) - cDownY);
                scrollTo(0, (int) (-move / moveRatio + getScrollY()));
                cDownY = ev.getY(activePointerIndex);
                moveRatio = (float) (Math.pow(getScrollY() / RATION_CONTROL, 2) * RATION_CONTROL / getHeight() + DEFAULT_MOVE_RATIO);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                cDownY = ev.getY(ev.getActionIndex());
                mActivePointerId = ev.getPointerId(ev.getActionIndex());
                break;
            case MotionEvent.ACTION_POINTER_UP:
                int pointerIndex = ev.getActionIndex();
                int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    int newIndex = pointerIndex == 0 ? 1 : 0;
                    mActivePointerId = ev.getPointerId(newIndex);
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                scrollBack();
                break;
            default:
                break;
        }
        return true;
    }

    /**
     * 松开手指回滚
     */
    private void scrollBack() {
        moveRatio = DEFAULT_MOVE_RATIO;

        int duration = (int) ((float) Math.abs(getScrollY()) / getHeight() * SCROLL_BACK_DURATION);
        duration = Math.min(duration, SCROLL_BACK_DURATION);
        ObjectAnimator backAnim = ObjectAnimator.ofInt(this, "scrollY", 0);
        backAnim.setDuration(duration);
        backAnim.setInterpolator(new DecelerateInterpolator());
        backAnim.start();
    }

    /**
     * 判断是否可以滚动
     *
     * @param dy dy>0，可以向下滚动，dy<0，可以向上滚动
     * @return true:可以滚动，false：不可以滚动
     */
    private boolean canScrollVertically(float dy) {
        if (dy > 0) {
            for (int i = 0; i < getChildCount(); i++) {
                if (getChildAt(i).canScrollVertically(-1)) {
                    return false;
                }
            }
            return true;
        } else if (dy < 0) {
            for (int i = 0; i < getChildCount(); i++) {
                if (getChildAt(i).canScrollVertically(1)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}
